package service.finder;

import dataAcsessObject.JPADAOFactory;
import entity.Course;
import entity.Professor;
import entity.University;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import valueObject.CourseVO;
import valueObject.ProfessorVO;
import valueObject.UniversityVO;
import valueObject.ValueObject;
import valueObjetcsView.ResultObject;

/**
 *
 * @author Juan Hernández Serrato
 */
public class FinderService {
    
    private List<UniversityVO> universitiesVO;
    private List<CourseVO> coursesVO;
    private List<ProfessorVO> professorsVO;
    
    private void init(EntityManager em){
        universitiesVO = (new ArrayList<UniversityVO>());
        List<University> universitys = JPADAOFactory.getInstance().getUniversityDAO().findAll(em);
        for (University university : universitys) {
            universitiesVO.add(university.toValueObject());
        }
        
        coursesVO = (new ArrayList<CourseVO>());
        List<Course> courses = JPADAOFactory.getInstance().getCourseDAO().findAll(em);
        for (Course course : courses) {
            coursesVO.add(course.toValueObject());
        }
        
        professorsVO = (new ArrayList<ProfessorVO>());
        List<Professor> professors = JPADAOFactory.getInstance().getProfessorDAO().findAll(em);
        for (Professor professor : professors) {
            professorsVO.add(professor.toValueObject());
        }
    }
    
    public List<ResultObject> findElements(String query, EntityManager em) throws IOException, ParseException{
        init(em);
        String queryStr = query.replace(" ", "~ ").concat("~");
        System.out.println(queryStr);
        StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);
        Directory index = new RAMDirectory();
        IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35, analyzer);
        IndexWriter w = new IndexWriter(index, config);
        
        for (CourseVO courseVO : coursesVO) {
            addDoc(w, courseVO);
            System.out.println("Añadido a la lista para buscar:" + courseVO.getDescription());
        }
        w.close();
        
        Query q = new QueryParser(Version.LUCENE_35, "descripcion", analyzer).parse(queryStr);
        int hitsPerPage = 10;
        IndexSearcher searcher = new IndexSearcher(index, true);
        TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true);
        searcher.search(q, collector);
        ScoreDoc[] hits = collector.topDocs().scoreDocs;

        // 4. display results
        List<ResultObject> resultObjects = new ArrayList<ResultObject>();
        for(int i=0;i<hits.length;++i) {
            ResultObject resultObject = new ResultObject();
            int docId = hits[i].doc;
            Document d = searcher.doc(docId);
            resultObject.setId(d.get("id"));
            resultObject.setDescription(d.get("descripcion"));
            System.out.println(resultObject.getDescription());
            if(d.get("tipo").compareTo(ResultType.COURSE.getResultType()) == 0) {
                resultObject.setResultType(ResultObject.ResultObjectType.COURSE);
            }
            if(d.get("tipo").compareTo(ResultType.PROFESSOR.getResultType()) == 0) {
                resultObject.setResultType(ResultObject.ResultObjectType.PROFESSOR);
            }
            if(d.get("tipo").compareTo(ResultType.UNIVERSITY.getResultType()) == 0) {
                resultObject.setResultType(ResultObject.ResultObjectType.UNIVERSITY);
            }
            resultObjects.add(resultObject);
        }
        searcher.close();
        return resultObjects;
    }
    
    private static void addDoc(IndexWriter w, ValueObject object) throws IOException {
        Document doc = new Document();
        String id="";
        String desc="";
        String type="";
        if(object instanceof CourseVO){
            id=((CourseVO)object).getId().toString();
            desc=((CourseVO)object).getName();
            type=ResultType.COURSE.getResultType();
        }
        if(object instanceof ProfessorVO){
            id=((ProfessorVO)object).getUserName().toString();
            desc=((ProfessorVO)object).getSurname() + " " + ((ProfessorVO)object).getName();
            type=ResultType.PROFESSOR.getResultType();
        }
        if(object instanceof UniversityVO){
            id=((UniversityVO)object).getUserName().toString();
            desc=((UniversityVO)object).getName();
            type=ResultType.UNIVERSITY.getResultType();
        }
        doc.add(new Field("id",id, Field.Store.YES, Field.Index.NOT_ANALYZED));
        doc.add(new Field("descripcion",desc, Field.Store.YES, Field.Index.ANALYZED));
        doc.add(new Field("tipo",type, Field.Store.YES, Field.Index.NOT_ANALYZED));
        w.addDocument(doc);
    }

    public List<UniversityVO> getUniversitiesVO() {
        return universitiesVO;
    }

    public void setUniversitiesVO(List<UniversityVO> universitiesVO) {
        this.universitiesVO = universitiesVO;
    }

    public List<CourseVO> getCoursesVO() {
        return coursesVO;
    }

    public void setCoursesVO(List<CourseVO> coursesVO) {
        this.coursesVO = coursesVO;
    }

    public List<ProfessorVO> getProfessorsVO() {
        return professorsVO;
    }

    public void setProfessorsVO(List<ProfessorVO> professorsVO) {
        this.professorsVO = professorsVO;
    }
}